#include <QApplication>
#include <QMap>
#include <QVariant>
#include <QySciEdit>
#include <QtScript>

#include "QySciLexer.h"
#include "Test.h"

/**************************************************************************************************/

inline void generatePropertyMap( const QScriptValue & object, const QString & name,
	QMap<QString,QVariant> & propertyMap )
{

	QScriptValueIterator it(object);

	while ( it.hasNext() ) {

		it.next();

		QScriptValue value( it.value() );
		QString valueName( it.name() );

		if ( value.isFunction() )
			continue;

		if ( name.count() )
			valueName = name + "." + valueName;

		if ( value.isObject() )
			generatePropertyMap( value, valueName, propertyMap );
		else
			propertyMap[valueName] = value.toVariant();

	}

}

/**************************************************************************************************/

QyLexerFactory::QyLexerFactory( QObject * parent ) : QObject(parent) {

	p_lexer = new QySciLexer(this);

}

QySciLexer * QyLexerFactory::lexer( const QString & ) {

	return p_lexer;
}

void QyLexerFactory::applySettings( const QScriptValue & value ) {

	QMap<QString,QVariant> propertyMap;

	generatePropertyMap( value, "", propertyMap );

	p_lexer->clearSettings();
	p_lexer->loadPropertyFromMap(propertyMap);

	// QStringList keys( propertyMap.keys() );

	// foreach ( QString key, keys )
		// qDebug() << key.toStdString().c_str() << "=" << propertyMap[key].toString() << "[" << propertyMap[key].typeName() << "]";

}

/**************************************************************************************************/

// Q_SCRIPT_DECLARE_QMETAOBJECT( QySciLexer, QObject * );

Q_DECLARE_METATYPE(QySciLexer*)

QScriptValue myObjectToScriptValue( QScriptEngine * engine, QySciLexer * const &in ) {

	return engine->newQObject(in);
}

void myObjectFromScriptValue( const QScriptValue & object, QySciLexer *& out ) {

	out = qobject_cast<QySciLexer*>( object.toQObject() );

}

/**************************************************************************************************/

inline const char * exStr( const QByteArray & str ) {

	return str.constData();
}

int main( int argc, char ** argv ) {

	QApplication app( argc, argv );
	QySciEdit * edit = new QySciEdit;
	QyLexerFactory * lexerFactory = new QyLexerFactory;
	QMap<QString,QVariant> map;

    QString fileName("./test.qs");
    QFile file(fileName);
    if (!file.open(QFile::ReadOnly)) {
        fprintf(stderr, "*** failed to open `%s' for reading\n", argv[1]);
        return(-1);
    }

    QString code = QTextStream(&file).readAll();
    file.close();

    QScriptEngine engine;

	qScriptRegisterMetaType( &engine, myObjectToScriptValue, myObjectFromScriptValue );

    engine.globalObject().setProperty( "lexerFactory", engine.newQObject(lexerFactory) );
    qDebug() << engine.evaluate( code, fileName ).toString();

	edit->setLexer( lexerFactory->lexer("C++") );
	edit->show();

	return app.exec();
}
